package org.truenewx.tnxjee.repo.redis.serializer;

import java.nio.charset.StandardCharsets;
import java.util.Map;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.truenewx.tnxjee.core.util.JacksonUtil;
import org.truenewx.tnxjee.core.util.JsonUtil;

/**
 * 通用的Jackson2 JSON序列化器，适用于绝大多数场合
 */
public class UniversalJackson2JsonRedisSerializer implements RedisSerializer<Object> {

    private ObjectMapper objectMapper;

    private ObjectMapper getObjectMapper() {
        if (this.objectMapper == null) { // 在使用时才初始化，以便于默认ObjectMapper注册附加模块
            this.objectMapper = JacksonUtil.withComplexClassProperty(JacksonUtil.copyDefaultMapper());
        }
        return this.objectMapper;
    }

    @Override
    public byte[] serialize(Object o) throws SerializationException {
        if (o == null) {
            return new byte[0];
        }
        try {
            return getObjectMapper().writeValueAsBytes(o); // 此处内部固定使用UTF-8编码写入
        } catch (Exception ex) {
            throw new SerializationException("Could not write JSON: " + ex.getMessage(), ex);
        }
    }

    @Override
    public Object deserialize(byte[] bytes) throws SerializationException {
        if (ArrayUtils.isNotEmpty(bytes)) {
            String content = new String(bytes, StandardCharsets.UTF_8); // 固定使用UTF-8编码读取
            try {
                if (content.contains(JacksonUtil.CLASS_PROPERTY_KEY)) {
                    // 含@class的JSON串用复合类型反序列化
                    return getObjectMapper().readValue(content, new TypeReference<>() {
                    });
                } else if (JsonUtil.isComplexJson(content)) {
                    // 不含@class又是复合类型的JSON串用Map反序列化
                    return getObjectMapper().readValue(content, Map.class);
                } else {
                    // 剩余其它用Object反序列化
                    return getObjectMapper().readValue(content, Object.class);
                }
            } catch (JsonProcessingException e) {
                // 如果反序列化因为缺少@class而失败，可能是附加的注册模块未来得及生效，此时将objectMapper置为null，以便使得注册模块生效
                if (e.getMessage().contains("missing type id property '" + JacksonUtil.CLASS_PROPERTY_NAME + "'")) {
                    this.objectMapper = null;
                }
                throw new SerializationException("Could not read JSON: " + content + "\n", e);
            }
        }
        return null;
    }

}
